## C/C++ OpenGL+GLUT for Linux
## Makefile by Corentin Le Molgat (2008/03/30)
## see http://www.gnu.org/software/make/manual/make.html

# special goals :
# make						# compile + ls -h
# make run				# run program
# make release    # compile + strip + upx + ls -h(x3)
# make wc					# display number of coding lines
# make valgrind		# run valgrind on the binary

# no more than one goal
ifeq ($(shell [ $(words $(MAKECMDGOALS)) -gt 1 ]; echo $$?),0)
$(error Please specify only one goal at a time)
endif

# name of binary + sources
include config.mk

LINUX = linux
# name of the binary
TARGET = Mizu!
# Glut library static linked ?
STATIC = no
# Verbose version for debugging
DEBUG = no

## platform specific variables
# Linux
ifeq ($(shell uname),Linux)
PLATFORM = $(LINUX)
LDFLAGS = -L/usr/lib 
endif

# some general flags
CFLAGS := -W -Wall
# debug mode, ie make clean; make DEBUG=1
ifeq ($(DEBUG),yes)
CFLAGS := -g -O0 -DDEBUG $(CFLAGS)
else
CFLAGS := -O3 $(CFLAGS)
endif
CXXFLAGS :=$(CFLAGS) -ansi -pedantic -fno-strict-aliasing

IDFLAGS :=  -I. -I/usr/include -I/usr/include/GL
ifeq ($(STATIC),yes)
GLLIBS 	:= -lGL -lGLU -lGLEW /usr/lib/libglut.a
else
GLLIBS 	:= -lGL -lGLU -lGLEW -lglut
endif
LIBS	:= $(GLLIBS) 
###########################################################
# YOU SHOULD NOT NEED TO EDIT BELOW THIS LINE
###########################################################

# figure out if there is at least one C++ source file
# if there is one, g++ will be used to link the objects
ifeq ($(findstring .cpp,$(SRC)),.cpp)
LNK = $(CXX)
CPPFLAGS = $(CXXFLAGS)
else
LNK = $(CC)
CPPFLAGS = $(CFLAGS)
endif

# directories
ifeq ($(BINDIR),)
BINDIR = $(PLATFORM)/bin
endif
OBJDIR = $(PLATFORM)/obj
DEPDIR = $(PLATFORM)/dep

# recreate sources dir tree
SRCTREE = $(dir $(SRC))
# sort removes duplicate words :)
OBJTREE = $(subst ./,,$(sort $(addprefix $(OBJDIR)/,$(SRCTREE))))
DEPTREE = $(subst ./,,$(sort $(addprefix $(DEPDIR)/,$(SRCTREE))))

# files
BIN = $(BINDIR)/$(TARGET)
AAA = $(SRC:.c=.o)
BBB = $(AAA:.cpp=.o)
OBJ = $(addprefix $(OBJDIR)/,$(BBB))
CCC = $(BBB:.o=.d)
DEP = $(addprefix $(DEPDIR)/,$(CCC))

# programs
MKDIR = mkdir -p
STRIP = strip --strip-all
UPX = upx --best
RM = rm -rf
ifeq ($(origin CC),default)
CC = gcc
endif
ifeq ($(origin CXX),default)
CXX = g++
endif

# rules that are not files
.PHONY : all

# 'make' calls the first rule found
all : $(BIN)

# link
$(BIN) : $(DEPTREE) $(DEP) $(OBJTREE) $(OBJ) $(BINDIR)
	$(LNK) $(OBJ) $(LDFLAGS) $(LIBS) -o $@
	ls -lh $(BIN)

# create output directory
$(BINDIR) :
	$(MKDIR) $(BINDIR)

# create tree where objects files will be
$(OBJTREE) :
	$(MKDIR) $(OBJTREE)

# create tree where dependencies files will be
$(DEPTREE) :
	$(MKDIR) $(DEPTREE)

# compile C
$(OBJDIR)/%.o : %.c
	$(CC)  $(CFLAGS) $(IDFLAGS) -c -o $@ $<

# compile C++
$(OBJDIR)/%.o : %.cpp
	$(CXX) $(CXXFLAGS) $(IDFLAGS) -c -o $@ $<

# include dependencies files (if directory $(DEPDIR) exists)
ifeq ($(shell [ -d $(DEPDIR) ]; echo $$?),0)
# and the goal is not `clean'
ifneq ($(MAKECMDGOALS),clean)
include $(DEP)
endif
endif

# solving the headers dependencies problem...
# http://www.gnu.org/software/make/manual/make.html#Automatic-Prerequisites
$(DEPDIR)/%.d : %.c
	@echo generating dependencies for $<...
	@set -e; rm -f $@; \
		/bin/echo -n $(OBJDIR)/ > $@.$$$$; $(CC) -MM $(CPPFLAGS) $< >> $@.$$$$; \
		sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$

$(DEPDIR)/%.d : %.cpp
	@echo generating dependencies for $<...
	@set -e; rm -f $@; \
		/bin/echo -n $(OBJDIR)/ > $@.$$$$; $(CXX) -MM $(CPPFLAGS) $< >> $@.$$$$; \
		sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; rm -f $@.$$$$

# rules that are not files
.PHONY : clean run release wc valgrind

# remove directories
clean :
	$(RM) $(BINDIR)
	$(RM) $(OBJDIR)
	$(RM) $(DEPDIR)
	$(RM) $(PLATFORM)

# simple run rule :)
run : $(BIN)
	@$(BIN)

# remove debugging info (reduces file size)
release : $(BIN)
	$(STRIP) $(BIN)
	ls -lh $(BIN)
	$(UPX) $(BIN)
	ls -lh $(BIN)

wc :
	wc */*.*

valgrind : $(BIN)
	valgrind $(BIN)

